По умолчанию система не уведомляет службы о событиях управления питанием. Система осуществляет переходы между различными режимами энергопотребления, не требуя никаких действий со стороны служб.
Если Ваша служба должна участвовать в принятии решений об управлении питанием:
Выполните следующие действия, чтобы получать уведомления о событиях управления питанием:
Служба должна сообщить системе, что она будет принимать и обрабатывать сообщения об управлении питанием следующим образом: При вызове службой функции SetServiceStatus должен устанавливаться бит SERVICE_ACCEPT_POWEREVENT в поле dwControlsAccepted структуры SERVICE_STATUS.
Управляющая функция-обработчик службы должна быть функцией «HandlerEx», как описано в документе по адресу
http://msdn.microsoft.com/library/sdkdoc/winbase/services_3smw.htm
Службы должны использовать функцию RegisterServiceCtrlHandlerEx для регистрации управляющей функции-обработчика «HandlerEx». Управляющие функции-обработчики «HandlerEx» поддерживают новые управляющие коды события управления питанием (в то время как управляющие функции-обработчики типа «Handler» не поддерживают).
После того включения уведомлений о событиях управления питанием Вашей службы она должна будет отвечать на управляющие запросы SERVICE_CONTROL_POWEREVENT и обрабатывать их точно так же, как и сообщения WM_POWERBROADCAST, перечисленные ранее в этой главе и необходимые для соответствия требованиям OnNow/ACPI. Получение сообщения SERVICE_CONTROL_POWEREVENT эквивалентно получению сообщения WM_POWERBROADCAST.
Сравнение уведомлений об управлении питанием
Первая ячейка | Вторая ячейка | |
Не службы | Службы | |
Событие управления питанием | WM_POWERBROADCAST | SERVICE_CONTROL_POWEREVENT |
Параметр события | wParam | dwEventType |
Параметр события | lParam | lpEventData |
Если запрос принят | Вернуть TRUE | Вернуть NO_ERROR |
Если запрос отклонен | Вернуть BROADCAST_QUERY_DENY | Вернуть любой код ошибки |
Пример OnNow:
В приведенном ниже примере показана обработка сообщений об управлении питанием в процедуре wndproc.
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG) // // НАЗНАЧЕНИЕ: Обработка сообщений, приходящих главному окну. // // WM_COMMAND - обработка меню приложения // WM_PAINT - рисование главного окна // WM_DESTROY - отправка сообщения о выходе и возврат // // BOOL g_bAvoidIO = FALSE; TCHAR g_szTitle[] = _T("Ждущий режим"); TCHAR g_szText[] = _T("Получен запрос о переходе в ждущий режим. ") _T("Закрыть все файлы и соединения?"); LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; SYSTEM_POWER_STATUS Status; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Разбор выбора из меню switch (wmId) { case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_POWERBROADCAST: switch(wParam) { case PBT_APMBATTERYLOW: // Аккумулятор разряжен. Используется для определения, // нужно ли отменить любой ввод/вывод или можно // использовать столько энергии, сколько необходимо. g_bAvoidIO = TRUE; break; case PBT_APMOEMEVENT: // Специфические события OEM break; case PBT_APMPOWERSTATUSCHANGE: // Компьютер был помещен или изъят из стационарного устройства, срок работы // аккумулятора менее 5 минут, осталось 10% мощности аккумулятора, энергия // аккумулятора изменилась на 3% и т.д. Нас интересует только, подключен ли // компьютер к сети. При питании от аккумулятора необходимо экономно // расходовать энергию. // Здесь можно производить и другие действия, например, если // выполняется операция, которая продлится дольше, чем // остается времени (мощности) работы аккумулятора, // Вы можете остановить процесс и проинформировать пользователя о том, // что времени для завершения текущей операции // недостаточно. GetSystemPowerStatus(&Status); g_bAvoidIO = Status.ACLineStatus == 1 ? FALSE : TRUE; break; case PBT_APMQUERYSUSPEND: // Если потери или повреждения данных не произошло, всегда возвращать // TRUE. Если данные могли быть потеряны или повреждены, // проверяйте старший бит значения lParam перед отображением любого // элемента интерфейса пользователя. // Если пользователь не ответит за разумное // время, система перейдет в ждущий режим, так что НЕ ДЕЛАЙТЕ ТАК // без крайней необходимости. if (g_bNetDataDirty ) { if(lParam & 0x00000001) { if (IDNO == MessageBox(hWnd, g_szText, g_szTitle, MB_YESNO | MB_ICONQUESTION | MB_SYSTEMMODAL)) return BROADCAST_QUERY_DENY; else // Пользователь требует перехода в спящий режим // с потерей сетевых данных. return TRUE; } else return BROADCAST_QUERY_DENY; } else return TRUE; case PBT_APMQUERYSUSPENDFAILED: // В обработчике PBT_APMQUERYSUSPEND мы ничего не делаем, так что // нет необходимости делать что-либо здесь. Если бы в уведомлении // PBT_APMQUERYSUSPEND что-то происходило, здесь // надо было бы отменять эти действия. break; case PBT_APMRESUMEAUTOMATIC: // Это уведомление необходимо обрабатывать, если бы мы обрабатывали // восстановление при поступлении запроса из сети, // от модема и т.д. Мы НЕ хотим обрабатывать // эту ситуацию, так же как и событие PBT_APMRESUMESUSPEND // потому что в этот момент нет взаимодействия с пользователем. Как // только система Windows обнаружит вмешательство пользователя // (передвижение мыши, нажатие клавиши и т.д.), система // сообщит об этом с помощью уведомления PBT_RESUMESUSPEND. break; case PBT_APMRESUMECRITICAL: // Данное уведомление означает, что система перешла в ждущий режим, // не отправив приложениям соответствующие сообщения. Приложение // должно восстановить сетевые соединения, // повторно открыть все файлы и восстановить общее // состояние приложения. Также необходимо попытаться определить // возможную потерю или повреждение данных и уведомить пользователя. break; case PBT_APMRESUMESUSPEND: // Восстановить все сетевые соединения, сохраненные в функции suspend // и/или повторно открыть все файлы и переместить указатели // текущего положения на сохраненные позиции. // Если файлы находятся на локальном диске, их состояние будет // сохранено; Вам нужно будет отслеживать, какие файлы находятся // на локальных дисках, а какие на сетевых // устройствах. Resume(); break; case PBT_APMSUSPEND: // Сохраните необходимую информацию для восстановления сетевых // соединений и/или закройте все файлы и сохраните информацию, // необходимую для восстановления состояния каждого файла (имя // файла/путь, позиция указателя в файле и т.д.). Suspend(); break; } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }